
#include "AnimationCtrl.h"
#include "../VMain.h"

extern SingerCoversDeque g_CoverDeque;

#ifdef UNDER_CE
#define KPI 3.1415926
static void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear,  GLfloat zFar)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    double xmin, xmax, ymin, ymax;
    ymax = zNear * tan(fovy * KPI / 360);
    ymin = -ymax;
    xmin = ymin * aspect;
    xmax = ymax * aspect;

    glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
    glMatrixMode(GL_MODELVIEW);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glDepthMask(GL_TRUE);
}

static void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,

                      GLfloat centerx, GLfloat centery, GLfloat centerz,

                      GLfloat upx, GLfloat upy, GLfloat upz)

{

    GLfloat m[16];

    GLfloat x[3], y[3], z[3];

    GLfloat mag;


    /* Make rotation matrix */

    /* Z vector */

    z[0] = eyex - centerx;

    z[1] = eyey - centery;

    z[2] = eyez - centerz;

    mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);

    if (mag)                     /* mpichler, 19950515 */
    {

        z[0] /= mag;

        z[1] /= mag;

        z[2] /= mag;

    }

    /* Y vector */

    y[0] = upx;

    y[1] = upy;

    y[2] = upz;

    /* X vector = Y cross Z */

    x[0] = y[1] * z[2] - y[2] * z[1];

    x[1] = -y[0] * z[2] + y[2] * z[0];

    x[2] = y[0] * z[1] - y[1] * z[0];

    /* Recompute Y = Z cross X */

    y[0] = z[1] * x[2] - z[2] * x[1];

    y[1] = -z[0] * x[2] + z[2] * x[0];

    y[2] = z[0] * x[1] - z[1] * x[0];

    /* mpichler, 19950515 */

    /* cross product gives area of parallelogram, which is < 1.0 for

    * non-perpendicular unit-length vectors; so normalize x, y here

    */

    mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);

    if (mag)
    {

        x[0] /= mag;

        x[1] /= mag;

        x[2] /= mag;

    }

    mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);

    if (mag)
    {

        y[0] /= mag;

        y[1] /= mag;

        y[2] /= mag;

    }

#define M(row,col)  m[col*4+row]

    M(0, 0) = x[0];

    M(0, 1) = x[1];

    M(0, 2) = x[2];

    M(0, 3) = 0.0;

    M(1, 0) = y[0];

    M(1, 1) = y[1];

    M(1, 2) = y[2];

    M(1, 3) = 0.0;

    M(2, 0) = z[0];

    M(2, 1) = z[1];

    M(2, 2) = z[2];

    M(2, 3) = 0.0;

    M(3, 0) = 0.0;

    M(3, 1) = 0.0;

    M(3, 2) = 0.0;

    M(3, 3) = 1.0;

#undef M

    glMultMatrixf(m);
    /* Translate Eye to Origin */
    glTranslatef(-eyex, -eyey, -eyez);
}
#endif

CSingerAnimationCtrl::CSingerAnimationCtrl(void)
{
    m_CenterIndex = g_CoverDeque.size() / 2;
    m_flag = 0;
}

CSingerAnimationCtrl::~CSingerAnimationCtrl(void)
{
}

void CSingerAnimationCtrl::StartAnimation(int nDirection)
{
    if (0 == g_CoverDeque.size())
    {
        return;
    }

    m_flag = nDirection;
    //  m_dwStartTime = timeGetTime();
    m_dwStartTime = VMain::getClock();
    m_bIsPlaying  = true;
}

void CSingerAnimationCtrl::StopAnimation()
{
    m_flag           = 0;
    m_dwStartTime    = 0;
    m_fPosPerSeconds = 0;
    m_bIsPlaying     = false;
}

void CSingerAnimationCtrl::Update()
{
    if (0 == m_flag || 0 == g_CoverDeque.size())
    {
        return;
    }

    //如果向左滑动时,中心已经在最右端,则返回
    if (-1 == m_flag && m_CenterIndex == g_CoverDeque.size() - 1)
    {
        return;
    }

    //如果向右滑动时,中心已经在最左端,则返回
    if (1 == m_flag && m_CenterIndex == 0)
    {
        return;
    }

    float dwTmp = VMain::getClock();

    m_fPosPerSeconds = (dwTmp - m_dwStartTime) / g_nPlayTime;

    if (m_fPosPerSeconds > 1.0)
    {
        if (-1 == m_flag)//如果向左滑动,中心则向右移动
        {
            m_CenterIndex++;

            if (m_CenterIndex > (int)g_CoverDeque.size() - 1) //如果中心已经到最右端,说明不能再向左滑动了
            {
                m_CenterIndex = g_CoverDeque.size() - 1;
            }
        }

        if (1 == m_flag) //如果向右滑动,中心则向左移动
        {
            m_CenterIndex--;

            if (m_CenterIndex < 0)//如果中心已经到最左端,说明不能再向右滑动了
            {
                m_CenterIndex = 0;
            }
        }

        StopAnimation();
        ResetData();
        return;
    }

    DrawSlidesCover(m_fPosPerSeconds * m_flag);
    DrawCenterCover(m_fPosPerSeconds * m_flag);
    DrawSlideCover(m_CenterIndex - m_flag, m_fPosPerSeconds * m_flag);

}

//一次至多画18个,提高效率
void CSingerAnimationCtrl::Render(void)
{
    int i = m_CenterIndex - RENDERNUMS;

    if (i < 0)
    {
        i = 0;
    }

    for (; i < (int)g_CoverDeque.size(); i++)
    {
        g_CoverDeque[i]->Render();

        if (i >= m_CenterIndex + RENDERNUMS)
        {
            break;
        }
    }
}

void CSingerAnimationCtrl::DrawCenterCover(float factor)
{
    CVector pos;
    g_CoverDeque[m_CenterIndex]->m_fAngle = -g_fAngle * factor;

    pos.x =  g_Interval * factor * .8;
    pos.y = 0;

    if (m_flag == 1)
    {
        pos.z = g_CenterZ - g_CenterZ * factor;
    }
    else
    {
        pos.z = g_CenterZ + g_CenterZ * factor;
    }

    g_CoverDeque[m_CenterIndex]->m_v3Position = pos;
}

void CSingerAnimationCtrl::DrawSlideCover(int Index, float factor)
{
    CVector pos;
    g_CoverDeque[Index]->m_fAngle = (g_fAngle * m_flag - g_fAngle * factor);

    if (m_flag == -1)
    {
        pos.x = g_Interval * .8 + g_Interval * factor * .8;
        pos.z = -g_CenterZ * factor;
    }
    else
    {
        pos.x = -g_Interval * .8 + g_Interval * factor * .8;
        pos.z = g_CenterZ * factor;
    }

    pos.y = 0;
    g_CoverDeque[Index]->m_v3Position = pos;
}

void CSingerAnimationCtrl::DrawSlidesCover(float factor)
{
    int i, j = 1;
    CVector pos;

    for (i = m_CenterIndex - 1; i >= 0; i--)
    {
        pos.x = -j * g_Interval * .8 + g_Interval * factor * .8;
        pos.y = 0;
        pos.z = 0;
        g_CoverDeque[i]->m_v3Position = pos;
        j++;

        if (i < m_CenterIndex - RENDERNUMS)//为提高效率,限制更改数据个数
        {
            break;
        }
    }

    j = 1;

    for (i = m_CenterIndex + 1; i < (int)g_CoverDeque.size(); i++)
    {
        pos.x = j * g_Interval * .8 + g_Interval * factor * .8;
        pos.y = 0;
        pos.z = 0;
        g_CoverDeque[i]->m_v3Position = pos;
        j++;

        if (i > m_CenterIndex + RENDERNUMS)//为提高效率,限制更改数据个数
        {
            break;
        }
    }
}

void CSingerAnimationCtrl::SetCenterIndex(int nIndex)
{
    if (0 == g_CoverDeque.size())
    {
        return;
    }

    if (nIndex < 0)
    {
        nIndex = 0;
    }

    if (nIndex >= (int)g_CoverDeque.size())
    {
        nIndex = (int)g_CoverDeque.size() - 1;
    }

    m_CenterIndex = nIndex;
    ResetData();
}

void CSingerAnimationCtrl::SetOpenGL(int nLeft, int nTop, int nWidth, int nHeight)
{

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    glViewport(nLeft, VIEWPORT_HEIGHT - nHeight - nTop, nWidth, nHeight);
    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();
    gluPerspective(25.0f,
                   (GLfloat)nWidth / (GLfloat)nHeight,
                   1.0f, 100.0f);
    //  gluLookAt(
    //      摄像机x,摄像机y,摄像机z,
    //      目标点x,目标点y,目标点z,
    //      摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z
    //      )
//    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0,-0.5f,-5);
}

int CSingerAnimationCtrl::GetCenterIndx()
{
    return m_CenterIndex;
}

void CSingerAnimationCtrl::ResetData()
{
    int i;

    for (i = m_CenterIndex ; i > 0; i--)
    {
        g_CoverDeque[i]->m_v3Position.x = -((m_CenterIndex - i - 1) * g_IntervalCover + g_Interval) * .8;
        g_CoverDeque[i]->m_v3Position.y = 0;
        g_CoverDeque[i]->m_v3Position.z = 0;
        g_CoverDeque[i]->m_fAngle = g_fAngle;

        if (i < m_CenterIndex - RENDERNUMS) // 为提高效率,限制更改数据个数
        {
            break;
        }
    }

    for (i = m_CenterIndex ; i < (int)g_CoverDeque.size(); i++)
    {
        g_CoverDeque[i]->m_v3Position.x = ((i - m_CenterIndex - 1) * g_IntervalCover + g_Interval) * .8;;
        g_CoverDeque[i]->m_v3Position.y = 0;
        g_CoverDeque[i]->m_v3Position.z = 0;
        g_CoverDeque[i]->m_fAngle = -g_fAngle;

        if (i > m_CenterIndex + RENDERNUMS) // 为提高效率,限制更改数据个数
        {
            break;
        }
    }

    g_CoverDeque[m_CenterIndex]->m_v3Position.x = 0;
    g_CoverDeque[m_CenterIndex]->m_v3Position.y = 0;
    g_CoverDeque[m_CenterIndex]->m_v3Position.z = g_CenterZ;
    g_CoverDeque[m_CenterIndex]->m_fAngle = 0;
}

//鼠标操作
void CSingerAnimationCtrl::MouseTrace(int x)
{
    m_MouseTrace = m_MouseStart - x;

    if (m_MouseTrace > 0)//从右向左滑动
    {
        m_flag = -1;
        m_fPosPerSeconds = static_cast<float>(m_MouseTrace) / RULER;

        if (m_fPosPerSeconds > 1.0)
        {
            m_MouseStart = x;
            m_CenterIndex++;

            if (m_CenterIndex > static_cast<int>(g_CoverDeque.size() - 1)) //如果中心已经到最右端,说明不能再向左滑动了
            {
                m_CenterIndex = g_CoverDeque.size() - 1;
            }

            StopAnimation();
        }
    }

    if (m_MouseTrace < 0)//向右滑动
    {
        m_flag = 1;
        m_fPosPerSeconds = abs((float)m_MouseTrace) / RULER;

        if (m_fPosPerSeconds > 1.0)
        {
            m_MouseStart = x;
            m_CenterIndex--;

            if (m_CenterIndex < 0)//如果中心已经到最左端,说明不能再向右滑动了
            {
                m_CenterIndex = 0;
            }

            StopAnimation();
        }
    }
}

void CSingerAnimationCtrl::MouseStart(int start)
{
    m_MouseStart = start;
}

void CSingerAnimationCtrl::MouseUp()
{
    if (m_fPosPerSeconds < 1.0)
    {
        StartAnimation(m_flag);
    }
}
